// 定义一些常量
const PI = Math.PI; // 圆周率
const RAD = PI / 180; // 弧度单位
const DEG = 180 / PI; // 角度单位
const EPOCH = new Date(1985, 0, 1); // 基准年
const K = 79.6764; // 基准年的积日

// 定义一个函数，计算给定日期的积日
function getDayOfYear(date) {
    let start = new Date(date.getFullYear(), 0, 0);
    let diff = date - start;
    let oneDay = 1000 * 60 * 60 * 24;
    return Math.floor(diff / oneDay);
}

// 定义一个函数，计算给定日期的日角
function getSolarAngle(date) {
    let dayOfYear = getDayOfYear(date);
    let year = date.getFullYear();
    let N0 = K + 0.2422 * (year - EPOCH.getFullYear()) - Math.floor(0.25 * (year - EPOCH.getFullYear()));
    let theta = (dayOfYear - N0) * (360 / 365.2422) * RAD;
    return theta;
}

// 定义一个函数，计算给定日期的真平太阳时差
function getEquationOfTime(date) {
    let theta = getSolarAngle(date);
    let deltaT = -7.657 * Math.sin(theta) + 9.862 * Math.sin(2 * theta + 3.599) - 0.032 * Math.sin(3 * theta + 1.291);
    return deltaT;
}

// 定义一个函数，计算给定经度和标准经线的地理时差
function getTimeZoneOffset(longitude, meridian) {
    let offset = (meridian - longitude) * 4;
    return offset;
}

// 定义一个函数，计算给定日期、经度和标准经线的真太阳时
export function getApparentSolarTime(date, longitude, meridian = 120) {
    let localTime = date.getHours() + date.getMinutes() / 60 + date.getSeconds() / 3600; // 当地时间，单位为小时
    let deltaT = getEquationOfTime(date); // 真平太阳时差，单位为分钟
    let offset = getTimeZoneOffset(longitude, meridian); // 地理时差，单位为分钟
    let solarTime = localTime - offset / 60 + deltaT / 60; // 真太阳时，单位为小时
    return solarTime;
}

// 测试一下
let date = new Date(2023, 5, 16, 22, 42, 17); // 创建一个日期对象，2023年6月16日22:42:17
let longitude = 116.4; // 北京的经度
let meridian = 120; // 北京所在时区的标准经线

let solarTime = getApparentSolarTime(date, longitude, meridian); // 计算真太阳时

console.log(solarTime); // 输出真太阳时，22.4275小时，即22点25分39秒

